import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.awt.image.BufferedImage;
import javax.imageio.*;
import java.util.*;

/*
 * READ ME
 * 
 * This program is for generating matrices which indicates images in core shaders
 * When calling the program, you have to assign the filepath of which you want to generate matrices
 * There are a few options that you can edit, you can find them at the begining of the main function
 * 
 */

public class bitmapGenerator{

    @SuppressWarnings("resource")
    public static void main(String[] args) {
        //There are some options you can edit

        //This option tells whether colors would be displayed as a float number (or it would be an expression like 121.0/255.0)
        boolean simplerVector = true;
        //These two options tell whether a large image needs to be confirmed, and the maximum size that don't need to confirm
        boolean largeBitmapWarning = true;
        int largeBitmapSize = 4096;


        long startTime = System.currentTimeMillis();            //Program Runtime
        long waitingTime = 0L;                                  //Program Runtime
        if(args.length == 0){                                   //Every call of the program needs arguments
            System.out.println("Need at least a file path");
        }

        System.out.println("\n\n\n");

        for(int i = 0 ; i < args.length ; i++){                 //traverse all the file
            File file = new File(args[i]);                      //creating file object

            System.out.print("Operated " + file.getName());   //display file operating
            System.out.println(" (" + (i + 1) + "/" + args.length + ")");

            BufferedImage image = null;                         //declare a buffered image object
            int width = 0;                                      //image arguments
            int height = 0;
            int count = 0;
            int pointer = 0;

            try{
                image = ImageIO.read(file);                     //read image
                width = image.getWidth();
                height = image.getHeight();

                if (largeBitmapWarning && (width*height) >= largeBitmapSize) {  //confirm to operate a large image
                    System.out.print("WARNING ! ! ! File " + file.getName());
                    System.out.print(" is a very large image which includes " + (width*height));
                    System.out.println(" pixels (more than setting size of" + largeBitmapSize + ")");
                    System.out.println("Are you sure to continue ? (Y/N)");

                    long startWaitingTime = System.currentTimeMillis();     //Program Runtime
                    long endWaitingTime = 0L;

                    if(!(new Scanner(System.in).nextLine().equals("Y"))){  //Skip the large image
                        System.out.println("File " + file.getName() + " has been skipped!");

                        endWaitingTime = System.currentTimeMillis();        //Program Runtime
                        waitingTime += endWaitingTime - startWaitingTime;

                        continue;
                    }
                }

                System.out.println("\t Width:" + width + "; Height:" + height);     //display image data

            }catch(IOException e){
                e.printStackTrace();
            }

            Set<String> Colors = new LinkedHashSet<String>();               //create matrices (using Set class)
            List<String> Bitmap = new ArrayList<String>();

            for(int h = (height - 1) ; h >= 0 ; h--){                       //traverse all the pixel
                for(int w = 0 ; w < width ; w ++){

                    int pixel = image.getRGB(w, h);                         //get RGBA value
                    int R = (pixel >> 16) & 0xff;
                    int G = (pixel >> 8) & 0xff;
                    int B = pixel & 0xff;
                    int A = (pixel >> 24) & 0xff;

                    String colorVector = null;                              //creating colorVector
                    if(simplerVector){
                        colorVector = "vec4(" + (R/255f) + "," + (G/255f) + "," + (B/255f) + "," + (A/255f) + ")";
                    }else{
                        colorVector = "vec4(" + R + ".0/255.0," + G + ".0/255.0," + B + ".0/255.0," + A + ".0/255.0)"; 
                    }

                    if(Colors.add(colorVector)){                            //writing matrices (Bitmap and Colors)
                        Bitmap.add(String.valueOf(pointer));
                        pointer ++;
                    }else{
                        int repeatedPointer = bitmapGenerator.find(Colors, colorVector);
                        Bitmap.add(String.valueOf(repeatedPointer));
                    }

                    count ++;
                    if(count % largeBitmapSize == 0){
                        System.out.println(largeBitmapSize + " pixels have been operated ("+ count + "/" + (width*height) + ")");
                    }
                }
            }

            System.out.println("\t Bitmap has " + Bitmap.size() + " elements:");                            //display result
            if((width*height) < largeBitmapSize){
                System.out.println("\t\t" + Bitmap + "\n");
            }else{
                System.out.println("Please check the log file to get bitmap maxtrix (" + file.getAbsolutePath()+"_bitmap.log)");
            }
            System.out.println("\t Colors has " + Colors.size() + " elements:");
            if((width*height) < largeBitmapSize){
                System.out.println("\t\t" + Colors + "\n");
            }else{
                System.out.println("Please check the log file to get colors maxtrix (" + file.getAbsolutePath()+"_colors.log)");
            } 
            System.out.println("\t Operated " + count + " pixels in total");
            System.out.println("---------------------");

            try{                                                                                            //create log file
                PrintWriter pw = new PrintWriter(file.getAbsolutePath()+"_bitmap.log");
                pw.write(Bitmap.toString());
                pw.close();
                pw = new PrintWriter(file.getAbsolutePath()+"_colors.log");
                pw.write(Colors.toString());
                pw.close();
            }catch(IOException e){
                e.printStackTrace();
            }

        }
        long endTime = System.currentTimeMillis();                                                          //Program runtime
        System.out.println("Generate complete, " + (endTime - startTime - waitingTime) + "ms used.");
        System.out.println("===============");
    }

    //find index of element
    public static int find(Set<String> set, String targetElement){
        Iterator<String> iterator = set.iterator();  
        int index = 0;
        while (iterator.hasNext()) {  
            String element = iterator.next();  
            if (element.equals(targetElement)) {  
                break;  
            }  
            index++;  
        }
        return index;
    }
}

// Program by XuanYu1725